/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package se.kth.lwr.jeat.core;

import java.util.Collections;
import java.util.HashSet;
import java.util.Set;
import java.util.TreeMap;

/**
 * ActivitiCategories serves as a way of marking Activities and join
 * them into clusters. Through this mechanism it is possible to inspect the impact of
 * a group of Activities that is not hierarchically aggregated. See {@see Activity}
 * for further details.
 * <p/>
 * ActivityCategories also holds a reference to all existing ActivityCategories,
 * which can be acquired by the method <code>getCategories()</code>. There is a
 * standard set of ActivityCategories that are statically available from this 
 * class. However it is easy to expand the set of standard Categories. See 
 * <code>EmissionCategory</code> for examples.
 * 
 * <p/>
 * 
 * 
 * 
 * @see EmissionCategory
 * @see Activity
 * @author david
 */
public abstract class ActivityCategory extends Category<ActivityCategory> {

    private static HashSet<ActivityCategory> categories = new HashSet<>();
    private static TreeMap<ActivityCategory, HashSet<Activity>> links = new TreeMap<>();
    
    
/**
 * create an ActivityCategory
 * 
 * @param name name of category
 * @param description description of category
 */
    public ActivityCategory(String name, String description) {
        super(name, description);
        categories.add(this);
        links.put(this, new HashSet<Activity>());
        }

    /**Add the activity to a list of activities that belongs to this ActivityCategory
     * 
     * Denna metod är skyddad och nås inte utanför paketet. Avsikten är
     * att joinCategory i Activity skall användas istället eftersom
     * denna metod även underhåller listan med categorier som Aktiviteten
     * tillhör.
     * 
     * 
     * 
     * @param activity The Activity to add
     * @return true if the Activity was added. False if the Activity
     * allready belonged to this category
     */
    protected boolean addActitivity(Activity activity) {
        return links.get(this).add(activity);
    }
    
    /**Remove an activity from the list of activities linked to this category
     * 
     * @param activity The Activity to remove
     * @return true if the activity was removed. False if the activiy was not
     * linked with this category
     */

    protected boolean removeActivity(Activity activity) {
        return links.get(this).remove(activity);
    }

    /**Get all the Activities that have been marked with this category
     * as an unmodifiable List
     * 
     * @return a Set of Activities that belongs to this category
     */
    public final Set<Activity> getActivities() {
        Set<Activity> retval=Collections.unmodifiableSet(links.get(this));
        return retval;
    }
    
    /**
     * 
     * @return All registered ActivityCategories in an unmodifiable Set
     */
    
    @Override
    public final Set<ActivityCategory> getCategories(){
        return Collections.unmodifiableSet(categories);
    }
    
    
    /**Static access to all defined ActivityCategories
     * 
     * Tycker att det känns rätt med en statisk metod för att kunna erhålla
     * en referens till alla kategorier utan att först instansiera en
     * enskild kategori. Frågan är om man borde skippa getCategories i den
     * abstrakta generiska klassen?
     * 
     * @return All registered ActivityCategories in an unmodifiable Set
     */
    public static Set<ActivityCategory> categories(){
        return Collections.unmodifiableSet(categories);
    }
    
    // Here goes standard implementations:
    /**
     * All transport related activities
     */
    public static final ActivityCategory TRANSPORT =new ActivityCategory(
            "Transport", "All transport related activities") {};
    /**
     * All activities related to the production phase
     */
    public static final ActivityCategory PRODUCTION_PHASE= new ActivityCategory(
            "Production phase", "All activities related to the production phase") {};
    /**
     * All activities related to maintenance and operation
     */
    public static final ActivityCategory MAINTAINANCE_PHASE=new ActivityCategory(
            "Maintainance phase", "All activities related to maintenance and operation") {};
}

